<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>深入理解线程池 | JavaPool</title>
    <meta name="generator" content="VuePress 1.9.2">
    <link rel="icon" href="/img/favicon.ico">
    <meta name="description" content="java pool icu">
    <meta name="keywords" content="vuepress,theme,blog,vdoing">
    <meta name="theme-color" content="#a1cd00">
    
    <link rel="preload" href="/assets/css/0.styles.6964efbe.css" as="style"><link rel="preload" href="/assets/js/app.c5f14b06.js" as="script"><link rel="preload" href="/assets/js/2.0bb8723e.js" as="script"><link rel="preload" href="/assets/js/7.00cec9d7.js" as="script"><link rel="prefetch" href="/assets/js/10.56cf0803.js"><link rel="prefetch" href="/assets/js/11.3f64ae04.js"><link rel="prefetch" href="/assets/js/12.02afd2cb.js"><link rel="prefetch" href="/assets/js/13.635b7092.js"><link rel="prefetch" href="/assets/js/14.f10556e8.js"><link rel="prefetch" href="/assets/js/15.27d8470a.js"><link rel="prefetch" href="/assets/js/16.70efe620.js"><link rel="prefetch" href="/assets/js/17.a79eaec6.js"><link rel="prefetch" href="/assets/js/18.aa4c8485.js"><link rel="prefetch" href="/assets/js/19.d98d039e.js"><link rel="prefetch" href="/assets/js/20.31b4dba4.js"><link rel="prefetch" href="/assets/js/21.c5f5372e.js"><link rel="prefetch" href="/assets/js/3.36e473cd.js"><link rel="prefetch" href="/assets/js/4.862e5a4f.js"><link rel="prefetch" href="/assets/js/5.81a4a7b6.js"><link rel="prefetch" href="/assets/js/6.634b1bae.js"><link rel="prefetch" href="/assets/js/8.165e4749.js"><link rel="prefetch" href="/assets/js/9.5122111b.js">
    <link rel="stylesheet" href="/assets/css/0.styles.6964efbe.css">
  </head>
  <body class="theme-mode-light">
    <div id="app" data-server-rendered="true"><div class="theme-container sidebar-open have-rightmenu"><header class="navbar blur"><div title="目录" class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><img src="/img/logo.png" alt="JavaPool" class="logo"> <span class="site-name can-hide">JavaPool</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <!----></div></header> <div class="sidebar-mask"></div> <div class="sidebar-hover-trigger"></div> <aside class="sidebar" style="display:none;"><!----> <!---->  <ul class="sidebar-links"><li><a href="/pages/f0d781/" class="sidebar-link">并发编程三大核心问题</a></li><li><a href="/pages/f94dea/" aria-current="page" class="active sidebar-link">深入理解线程池</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level2"><a href="/pages/f94dea/#_1-介绍" class="sidebar-link">1. 介绍</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_1-1-使用场景" class="sidebar-link">1.1 使用场景</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_1-2-好处" class="sidebar-link">1.2 好处</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_1-3-一个简单示例" class="sidebar-link">1.3 一个简单示例</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/f94dea/#_2-executor框架接口" class="sidebar-link">2. Executor框架接口</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_2-1-executor接口" class="sidebar-link">2.1 Executor接口</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_2-2-executorservice接口" class="sidebar-link">2.2 ExecutorService接口</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_2-3-abstractexecutorservice类" class="sidebar-link">2.3 AbstractExecutorService类</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_2-4-threadpoolexecutor" class="sidebar-link">2.4 ThreadPoolExecutor</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/f94dea/#_3-线程池状态" class="sidebar-link">3. 线程池状态</a></li><li class="sidebar-sub-header level2"><a href="/pages/f94dea/#_4-线程池参数" class="sidebar-link">4. 线程池参数</a></li><li class="sidebar-sub-header level2"><a href="/pages/f94dea/#_5-线程池创建" class="sidebar-link">5. 线程池创建</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_5-1-threadpoolexecutor方式" class="sidebar-link">5.1 ThreadPoolExecutor方式</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_5-2-fixedthreadpool" class="sidebar-link">5.2 FixedThreadPool</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_5-3-singlethreadexecutor" class="sidebar-link">5.3 SingleThreadExecutor</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_5-4-cachedthreadpool" class="sidebar-link">5.4 CachedThreadPool</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/f94dea/#_6-执行过程" class="sidebar-link">6. 执行过程</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_6-1-execute-方法" class="sidebar-link">6.1 execute()方法</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_6-2-addworker方法" class="sidebar-link">6.2 addWorker方法</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_6-3-worker类" class="sidebar-link">6.3 Worker类</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_6-4-runworker方法" class="sidebar-link">6.4 runWorker方法</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_6-5-gettask方法" class="sidebar-link">6.5 getTask方法</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_6-6-总结" class="sidebar-link">6.6 总结</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/f94dea/#_7-关闭线程池" class="sidebar-link">7. 关闭线程池</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_7-1-shutdown方法" class="sidebar-link">7.1 shutdown方法</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_7-2-tryterminate方法" class="sidebar-link">7.2 tryTerminate方法</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_7-3-shutdownnow方法" class="sidebar-link">7.3 shutdownNow方法</a></li></ul></li><li class="sidebar-sub-header level2"><a href="/pages/f94dea/#_8-其他问题" class="sidebar-link">8. 其他问题</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_8-1-任务拒绝策略" class="sidebar-link">8.1 任务拒绝策略</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_8-2-线程池的监控" class="sidebar-link">8.2 线程池的监控</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_8-3-线程池中的线程初始化" class="sidebar-link">8.3 线程池中的线程初始化</a></li><li class="sidebar-sub-header level3"><a href="/pages/f94dea/#_8-4-线程池容量的动态调整" class="sidebar-link">8.4 线程池容量的动态调整</a></li></ul></li></ul></li><li><a href="/pages/6c4806/" class="sidebar-link">线程池</a></li><li><a href="/pages/76d299/" class="sidebar-link">并发编程-FutureTask</a></li></ul> </aside> <div><main class="page"><div class="theme-vdoing-wrapper "><div class="articleInfo-wrap" data-v-06225672><div class="articleInfo" data-v-06225672><ul class="breadcrumbs" data-v-06225672><li data-v-06225672><a href="/" title="首页" class="iconfont icon-home router-link-active" data-v-06225672></a></li> <li data-v-06225672><a href="/categories/?category=%E5%B9%B6%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B" title="分类" data-v-06225672>并发多线程</a></li></ul> <div class="info" data-v-06225672><div title="作者" class="author iconfont icon-touxiang" data-v-06225672><a href="https://mp.weixin.qq.com/s?__biz=MzAxMjEwMzQ5MA==&amp;mid=2448892737&amp;idx=2&amp;sn=e7130bd806fe95feba13cb5cee91741f&amp;scene=21#wechat_redirect" target="_blank" title="作者" class="beLink" data-v-06225672>java进阶架构师</a></div> <div title="创建时间" class="date iconfont icon-riqi" data-v-06225672><a href="javascript:;" data-v-06225672>2021-12-27</a></div> <!----></div></div></div> <!----> <div class="content-wrapper"><div class="right-menu-wrapper"><div class="right-menu-margin"><div class="right-menu-title">目录</div> <div class="right-menu-content"></div></div></div> <h1><img src="">深入理解线程池<span class="title-tag">转载</span></h1> <!----> <div class="theme-vdoing-content content__default"><h2 id="_1-介绍"><a href="#_1-介绍" class="header-anchor">#</a> 1. 介绍</h2> <h3 id="_1-1-使用场景"><a href="#_1-1-使用场景" class="header-anchor">#</a> 1.1 使用场景</h3> <p>并发编程可以高效利用CPU资源，提升任务执行效率，但是多线程及线程间的切换也伴随着资源的消耗。当遇到单个任务处理时间比较短，但需要处理的任务数量很大时，线程会频繁的创建销毁，大量的时间和资源都会浪费在线程的创建和销毁上，效率很低。</p> <p>这个时候就需要用的线程池了，线程作为一个工作者，线程执行完一个任务之后不销毁，而是继续执行其他的任务。</p> <h3 id="_1-2-好处"><a href="#_1-2-好处" class="header-anchor">#</a> 1.2 好处</h3> <ol><li>降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。</li> <li>提高响应速度。当任务到达时，任务可以不需要的等到线程创建就能立即执行。</li> <li>提高线程的可管理性。线程是稀缺资源，如果无限制的创建，不仅会消耗系统资源，还会降低系统的稳定性，使用线程池可以进行统一的分配，调优和监控。</li></ol> <h3 id="_1-3-一个简单示例"><a href="#_1-3-一个简单示例" class="header-anchor">#</a> 1.3 一个简单示例</h3> <p>先通过一个简单的示例了解下线程池：</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Test</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// 1. 创建线程池</span>
        <span class="token class-name">ThreadPoolExecutor</span> executor <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">200</span><span class="token punctuation">,</span> <span class="token class-name">TimeUnit</span><span class="token punctuation">.</span><span class="token constant">MILLISECONDS</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">ArrayBlockingQueue</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Runnable</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        
        <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">15</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token comment">// 2. 创建任务</span>
            <span class="token class-name">Runnable</span> task <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Runnable</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token annotation punctuation">@Override</span>
                <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                    <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">&quot;执行任务...&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">try</span> <span class="token punctuation">{</span>
                        <span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">currentThread</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
                        e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token punctuation">}</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span><span class="token punctuation">;</span>
            executor<span class="token punctuation">.</span><span class="token function">execute</span><span class="token punctuation">(</span>task<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 3. 任务交给线程池执行</span>
        <span class="token punctuation">}</span>
        executor<span class="token punctuation">.</span><span class="token function">shutdown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 4. 关闭线程池</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="_2-executor框架接口"><a href="#_2-executor框架接口" class="header-anchor">#</a> 2. Executor框架接口</h2> <p>Executor框架提供了一种“任务提交”与“任务如何运行”分离开来的机制，实现对异步任务的控制与执行。我们先大概了解下每个类的基本情况。</p> <p><img src="/assets/img/20210713004.67b5538c.png" alt=""></p> <h3 id="_2-1-executor接口"><a href="#_2-1-executor接口" class="header-anchor">#</a> 2.1 Executor接口</h3> <p>Executor接口只有一个execute方法，用于提交任务。</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">Executor</span> <span class="token punctuation">{</span>
    <span class="token keyword">void</span> <span class="token function">execute</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> command<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 启动线程执行任务</span>
<span class="token keyword">new</span> <span class="token class-name">Thread</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Runnable</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// TODO Auto-generated method stub</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// 使用Executor提交任务</span>
<span class="token class-name">Executor</span> executor <span class="token operator">=</span> newExecutor<span class="token punctuation">;</span>
executor<span class="token punctuation">.</span><span class="token function">execute</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">RunnableTask1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
executor<span class="token punctuation">.</span><span class="token function">execute</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">RunnableTask2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><h3 id="_2-2-executorservice接口"><a href="#_2-2-executorservice接口" class="header-anchor">#</a> 2.2 ExecutorService接口</h3> <p>ExecutorService接口继承自Executor接口，提供了线程池主要功能，提交任务、异步任务执行、关闭线程池等。</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ExecutorService</span> <span class="token keyword">extends</span> <span class="token class-name">Executor</span> <span class="token punctuation">{</span>
    <span class="token comment">// 关闭线程池，已提交的任务继续执行，不接受继续提交新任务</span>
    <span class="token keyword">void</span> <span class="token function">shutdown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">// 关闭线程池，尝试停止正在执行的所有任务，不接受继续提交新任务</span>
    <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Runnable</span><span class="token punctuation">&gt;</span></span> <span class="token function">shutdownNow</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">// 线程池是否已关闭</span>
    <span class="token keyword">boolean</span> <span class="token function">isShutdown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">// 如果调用了 shutdown() 或 shutdownNow() 方法后，所有任务结束了，那么返回true</span>
    <span class="token keyword">boolean</span> <span class="token function">isTerminated</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">// 提交一个 Callable 任务</span>
    <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">Future</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token function">submit</span><span class="token punctuation">(</span><span class="token class-name">Callable</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> task<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">// 提交一个 Runnable 任务，第二个参数将会放到 Future中，作为返回值，</span>
    <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">Future</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token function">submit</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> task<span class="token punctuation">,</span> <span class="token class-name">T</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">// 提交一个 Runnable 任务</span>
    <span class="token class-name">Future</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token operator">?</span><span class="token punctuation">&gt;</span></span> <span class="token function">submit</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> task<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">// 执行所有任务，返回 Future 类型的一个 list</span>
    <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Future</span><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span><span class="token punctuation">&gt;</span></span> <span class="token function">invokeAll</span><span class="token punctuation">(</span><span class="token class-name">Collection</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token operator">?</span> <span class="token keyword">extends</span> <span class="token class-name">Callable</span><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span><span class="token punctuation">&gt;</span></span> tasks<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">InterruptedException</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_2-3-abstractexecutorservice类"><a href="#_2-3-abstractexecutorservice类" class="header-anchor">#</a> 2.3 AbstractExecutorService类</h3> <p>AbstractExecutorService实现了ExecutorService接口，并在其基础上实现了几个实用的方法提供给子类进行调用。</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">AbstractExecutorService</span> <span class="token keyword">implements</span> <span class="token class-name">ExecutorService</span> <span class="token punctuation">{</span>

    <span class="token comment">/**
     * newTaskFor 方法用于将我们的任务包装成 FutureTask 提交到线程池中执行
     * RunnableFuture 是用于获取执行结果的，我们常用它的子类 FutureTask
     */</span>
    <span class="token keyword">protected</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">RunnableFuture</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token function">newTaskFor</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> runnable<span class="token punctuation">,</span> <span class="token class-name">T</span> value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">FutureTask</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>runnable<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">protected</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">RunnableFuture</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token function">newTaskFor</span><span class="token punctuation">(</span><span class="token class-name">Callable</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> callable<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">FutureTask</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>callable<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">/**
     * 提交任务
     */</span>
    <span class="token keyword">public</span> <span class="token class-name">Future</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token operator">?</span><span class="token punctuation">&gt;</span></span> <span class="token function">submit</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> task<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>task <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">NullPointerException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 1. 将任务包装成 FutureTask</span>
        <span class="token class-name">RunnableFuture</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Void</span><span class="token punctuation">&gt;</span></span> ftask <span class="token operator">=</span> <span class="token function">newTaskFor</span><span class="token punctuation">(</span>task<span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 2. 交给执行器执行</span>
        <span class="token function">execute</span><span class="token punctuation">(</span>ftask<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> ftask<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">Future</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token function">submit</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> task<span class="token punctuation">,</span> <span class="token class-name">T</span> result<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>task <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">NullPointerException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 1. 将任务包装成 FutureTask</span>
        <span class="token class-name">RunnableFuture</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> ftask <span class="token operator">=</span> <span class="token function">newTaskFor</span><span class="token punctuation">(</span>task<span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 2. 交给执行器执行</span>
        <span class="token function">execute</span><span class="token punctuation">(</span>ftask<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> ftask<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">Future</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token function">submit</span><span class="token punctuation">(</span><span class="token class-name">Callable</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> task<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>task <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">NullPointerException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 1. 将任务包装成 FutureTask</span>
        <span class="token class-name">RunnableFuture</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> ftask <span class="token operator">=</span> <span class="token function">newTaskFor</span><span class="token punctuation">(</span>task<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 2. 交给执行器执行</span>
        <span class="token function">execute</span><span class="token punctuation">(</span>ftask<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> ftask<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    
    <span class="token comment">// 将 tasks 集合中的任务提交到线程池执行，任意一个线程执行完后就可以结束了</span>
    <span class="token keyword">public</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">T</span> <span class="token function">invokeAny</span><span class="token punctuation">(</span><span class="token class-name">Collection</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token operator">?</span> <span class="token keyword">extends</span> <span class="token class-name">Callable</span><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span><span class="token punctuation">&gt;</span></span> tasks<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">InterruptedException</span><span class="token punctuation">,</span> <span class="token class-name">ExecutionException</span> <span class="token punctuation">{</span>
        <span class="token keyword">try</span> <span class="token punctuation">{</span>
            <span class="token keyword">return</span> <span class="token function">doInvokeAny</span><span class="token punctuation">(</span>tasks<span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">TimeoutException</span> cannotHappen<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">assert</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 执行所有的任务，返回任务结果。</span>
    <span class="token keyword">public</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Future</span><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span><span class="token punctuation">&gt;</span></span> <span class="token function">invokeAll</span><span class="token punctuation">(</span><span class="token class-name">Collection</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token operator">?</span> <span class="token keyword">extends</span> <span class="token class-name">Callable</span><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span><span class="token punctuation">&gt;</span></span> tasks<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">InterruptedException</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>

<span class="token punctuation">}</span>
</code></pre></div><h3 id="_2-4-threadpoolexecutor"><a href="#_2-4-threadpoolexecutor" class="header-anchor">#</a> 2.4 ThreadPoolExecutor</h3> <p>ThreadPoolExecutor就是线程池了，继承自AbstractExecutorService</p> <h2 id="_3-线程池状态"><a href="#_3-线程池状态" class="header-anchor">#</a> 3. 线程池状态</h2> <ul><li><p>RUNNING ：能接受新提交的任务，并且也能处理阻塞队列中的任务；</p></li> <li><p>SHUTDOWN：关闭状态，不再接受新提交的任务，但却可以继续处理阻塞队列中已保存的任务。在线程池处于 RUNNING 状态时，调用 shutdown()方法会使线程池进入到该状态。（finalize() 方法在执行过程中也会调用- shutdown()方法进入该状态）；</p></li> <li><p>STOP：不能接受新任务，也不处理队列中的任务，会中断正在处理任务的线程。在线程池处于 RUNNING 或 SHUTDOWN 状态时，调用 shutdownNow() 方法会使线程池进入到该状态；</p></li> <li><p>TIDYING：如果所有的任务都已终止了，workerCount (有效线程数) 为0，线程池进入该状态后会调用 terminated() 方法进入TERMINATED 状态。</p></li> <li><p>TERMINATED：在terminated() 方法执行完后进入该状态，默认terminated()方法中什么也没有做。进入TERMINATED的条件如下：</p></li> <li><ol><li>线程池不是RUNNING状态；</li> <li>线程池状态不是TIDYING状态或TERMINATED状态；</li> <li>如果线程池状态是SHUTDOWN并且workerQueue为空；</li> <li>workerCount为0；</li> <li>设置TIDYING状态成功。</li></ol></li></ul> <p><img src="/assets/img/20210713005.a0094bd9.png" alt=""></p> <p>线程状态如何保存呢？</p> <p>ThreadPoolExecutor采用一个 32 位的整数（int变量ctl）来存放线程池的状态和当前池中的线程数，其中高 3 位用于存放线程池状态，低 29 位表示线程数。</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token comment">// 高 3 位用于存放线程池状态，低 29 位表示线程数</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token class-name">AtomicInteger</span> ctl <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AtomicInteger</span><span class="token punctuation">(</span><span class="token function">ctlOf</span><span class="token punctuation">(</span><span class="token constant">RUNNING</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">/** 后29位用于存放线程数 */</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> <span class="token constant">COUNT_BITS</span> <span class="token operator">=</span> <span class="token class-name">Integer</span><span class="token punctuation">.</span><span class="token constant">SIZE</span> <span class="token operator">-</span> <span class="token number">3</span><span class="token punctuation">;</span>
<span class="token comment">// 000 11111111111111111111111111111</span>
<span class="token comment">// 最大线程数：这里得到的是 29 个 1，也就是说线程池的最大线程数是 2^29-1=536870911</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> <span class="token constant">CAPACITY</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token number">1</span> <span class="token operator">&lt;&lt;</span> <span class="token constant">COUNT_BITS</span><span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span>

<span class="token comment">/** 高 3 位表示线程池的状态 */</span>
<span class="token comment">// 111 00000000000000000000000000000</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> <span class="token constant">RUNNING</span> <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span> <span class="token operator">&lt;&lt;</span> <span class="token constant">COUNT_BITS</span><span class="token punctuation">;</span>
<span class="token comment">// 000 00000000000000000000000000000</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> <span class="token constant">SHUTDOWN</span> <span class="token operator">=</span> <span class="token number">0</span> <span class="token operator">&lt;&lt;</span> <span class="token constant">COUNT_BITS</span><span class="token punctuation">;</span>
<span class="token comment">// 001 00000000000000000000000000000</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> <span class="token constant">STOP</span> <span class="token operator">=</span> <span class="token number">1</span> <span class="token operator">&lt;&lt;</span> <span class="token constant">COUNT_BITS</span><span class="token punctuation">;</span>
<span class="token comment">// 010 00000000000000000000000000000</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> <span class="token constant">TIDYING</span> <span class="token operator">=</span> <span class="token number">2</span> <span class="token operator">&lt;&lt;</span> <span class="token constant">COUNT_BITS</span><span class="token punctuation">;</span>
<span class="token comment">// 011 00000000000000000000000000000</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> <span class="token constant">TERMINATED</span> <span class="token operator">=</span> <span class="token number">3</span> <span class="token operator">&lt;&lt;</span> <span class="token constant">COUNT_BITS</span><span class="token punctuation">;</span>

<span class="token comment">// 将整数 c 的低 29 位修改为 0，获取线程池的状态</span>
   <span class="token keyword">return</span> c <span class="token operator">&amp;</span> <span class="token operator">~</span><span class="token constant">CAPACITY</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// 将整数 c 的高 3 为修改为 0，获取线程池中的线程数</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">int</span> <span class="token function">workerCountOf</span><span class="token punctuation">(</span><span class="token keyword">int</span> c<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">return</span> c <span class="token operator">&amp;</span> <span class="token constant">CAPACITY</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="_4-线程池参数"><a href="#_4-线程池参数" class="header-anchor">#</a> 4. 线程池参数</h2> <p>线程池ThreadPoolExecutor类有四个构造方法，我们通过这个参数最全的构造方法来看下线程池参数：</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation">(</span><span class="token keyword">int</span> corePoolSize<span class="token punctuation">,</span>
        <span class="token keyword">int</span> maximumPoolSize<span class="token punctuation">,</span>
        <span class="token keyword">long</span> keepAliveTime<span class="token punctuation">,</span>
        <span class="token class-name">TimeUnit</span> unit<span class="token punctuation">,</span>
        <span class="token class-name">BlockingQueue</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Runnable</span><span class="token punctuation">&gt;</span></span> workQueue<span class="token punctuation">,</span>
        <span class="token class-name">ThreadFactory</span> threadFactory<span class="token punctuation">,</span>
        <span class="token class-name">RejectedExecutionHandler</span> handler<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span>corePoolSize <span class="token operator">&lt;</span> <span class="token number">0</span> <span class="token operator">||</span>
  maximumPoolSize <span class="token operator">&lt;=</span> <span class="token number">0</span> <span class="token operator">||</span>
  maximumPoolSize <span class="token operator">&lt;</span> corePoolSize <span class="token operator">||</span>
  keepAliveTime <span class="token operator">&lt;</span> <span class="token number">0</span><span class="token punctuation">)</span>
  <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span>workQueue <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span> threadFactory <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span> handler <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
  <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">NullPointerException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">this</span><span class="token punctuation">.</span>corePoolSize <span class="token operator">=</span> corePoolSize<span class="token punctuation">;</span>
 <span class="token keyword">this</span><span class="token punctuation">.</span>maximumPoolSize <span class="token operator">=</span> maximumPoolSize<span class="token punctuation">;</span>
 <span class="token keyword">this</span><span class="token punctuation">.</span>workQueue <span class="token operator">=</span> workQueue<span class="token punctuation">;</span>
 <span class="token keyword">this</span><span class="token punctuation">.</span>keepAliveTime <span class="token operator">=</span> unit<span class="token punctuation">.</span><span class="token function">toNanos</span><span class="token punctuation">(</span>keepAliveTime<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">this</span><span class="token punctuation">.</span>threadFactory <span class="token operator">=</span> threadFactory<span class="token punctuation">;</span>
 <span class="token keyword">this</span><span class="token punctuation">.</span>handler <span class="token operator">=</span> handler<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><ul><li><p><strong>corePoolSize：</strong> 核心线程数量；</p></li> <li><p><strong>maximumPoolSize：</strong> 最大线程数量；</p></li> <li><p><strong>workQueue：</strong> 等待队列，当线程池中的线程数量大于等于corePoolSize时，把该任务放入等待队列；</p></li> <li><p><strong>keepAliveTime：</strong> 线程池维护线程所允许的空闲时间。当线程池中的线程数量大于corePoolSize时，<strong>核心线程外的线程</strong>空闲时间超过keepAliveTime就会销毁；</p></li> <li><p><strong>unit：</strong> keepAliveTime的时间单位；</p></li> <li><p><strong>threadFactory：</strong> 用于创建新线程。默认使用Executors.defaultThreadFactory() 来创建线程。Executors.defaultThreadFactory() 创建的线程优先级都是NORM_PRIORITY；</p></li> <li><p><strong>handler：</strong> RejectedExecutionHandler类型的变量，表示线程池的拒绝策略。当阻塞队列满了并且没有空闲的线程时，如果继续提交任务，就需要采取一种策略处理该任务。线程池提供以下拒绝策略：</p></li> <li><ol><li>AbortPolicy：直接抛出异常，默认策略；</li> <li>CallerRunsPolicy：用调用者所在的线程来执行任务；</li> <li>DiscardOldestPolicy：丢弃阻塞队列中靠最前的任务，并执行当前任务；</li> <li>DiscardPolicy：直接丢弃任务；</li> <li>实现自己的拒绝策略，实现RejectedExecutionHandler接口重写rejectedExecution方法即可。</li></ol></li></ul> <p><strong>线程池任务提交过程：</strong></p> <p>任务提交的顺序为 corePoolSize –&gt; workQueue –&gt; maximumPoolSize -&gt; handler。</p> <ol><li>如果运行的线程数少于 corePoolSize，则创建新线程来处理任务，<strong>即使线程池中的其他线程是空闲的</strong>；</li> <li>如果运行的线程数大于等于 corePoolSize，则将任务放入workQueue中，等待有空闲的线程去从workQueue中取任务并处理；</li> <li>当workQueue已经满时，如果运行的线程数小于maximumPoolSize，则创建新的线程去处理提交的任务；</li> <li>当workQueue已经满时，如果运行的线程数大于等于maximumPoolSize且没有空闲线程，则通过handler所指定的拒绝策略来处理任务。</li></ol> <blockquote><p>线程池中的线程执行完当前任务后，会循环到任务队列中取任务继续执行；线程获取队列中任务时会阻塞，直到获取到任务返回；当线程数大于corePoolSize且线程阻塞时间超时，线程就会被销毁。</p></blockquote> <h2 id="_5-线程池创建"><a href="#_5-线程池创建" class="header-anchor">#</a> 5. 线程池创建</h2> <p>介绍四种创建线程池的方式：通过 ThreadPoolExecutor 的方式创建线程池及Executors工具类提供的三种创建方式。</p> <h3 id="_5-1-threadpoolexecutor方式"><a href="#_5-1-threadpoolexecutor方式" class="header-anchor">#</a> 5.1 ThreadPoolExecutor方式</h3> <p>直接调用 ThreadPoolExecutor 的构造方法，自己手动设置每一个参数，这是阿里推荐的方法。</p> <blockquote><p>【强制】线程池不允许使用 Executors 去创建，而是通过 ThreadPoolExecutor 的方式，这样的处理方式让写的同学更加明确线程池的运行规则，规避资源耗尽的风险。
——《阿里巴巴Java开发手册》</p></blockquote> <h3 id="_5-2-fixedthreadpool"><a href="#_5-2-fixedthreadpool" class="header-anchor">#</a> 5.2 FixedThreadPool</h3> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">ExecutorService</span> <span class="token function">newFixedThreadPool</span><span class="token punctuation">(</span><span class="token keyword">int</span> nThreads<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation">(</span>nThreads<span class="token punctuation">,</span> nThreads<span class="token punctuation">,</span>
          <span class="token number">0L</span><span class="token punctuation">,</span> <span class="token class-name">TimeUnit</span><span class="token punctuation">.</span><span class="token constant">MILLISECONDS</span><span class="token punctuation">,</span>
          <span class="token keyword">new</span> <span class="token class-name">LinkedBlockingQueue</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Runnable</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><ul><li>corePoolSize 和 maximumPoolSize都设置为指定nThreads，表示核心线程数等于最大线程数，当达到核心线程数且阻塞队列也已经满时，如果继续提交任务，则会直接走拒绝策略。</li> <li>FixedThreadPool使用的是默认的拒绝策略，即AbortPolicy，则直接抛出异常。</li> <li>keepAliveTime 表示线程数量大于corePoolSize时空闲的线程的存活时间，而FixedThreadPool的corePoolSize 和 maximumPoolSize相等，不可能有多余corePoolSize的线程，所以这里的keepAliveTime本来就无效。</li> <li>workQueue使用LinkedBlockingQueue，没有设置范围，默认是最大值（Integer.MAX_VALUE），相当于一个无界队列。当线程池中的线程数量等于corePoolSize 时，如果继续提交任务，该任务会被添加到阻塞队列workQueue中，因为workQueue是无界队列，所以maximumPoolSize和参数都无效。</li></ul> <h3 id="_5-3-singlethreadexecutor"><a href="#_5-3-singlethreadexecutor" class="header-anchor">#</a> 5.3 SingleThreadExecutor</h3> <p>newSingleThreadExecutor与FixedThreadPool类似，不过是将线程数设置为1。</p> <p>corePoolSize 和 maximumPoolSize都指定为1，表示该线程池中最多有一个线程，其他同FixedThreadPool。</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">ExecutorService</span> <span class="token function">newSingleThreadExecutor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">FinalizableDelegatedExecutorService</span>
  <span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span>
        <span class="token number">0L</span><span class="token punctuation">,</span> <span class="token class-name">TimeUnit</span><span class="token punctuation">.</span><span class="token constant">MILLISECONDS</span><span class="token punctuation">,</span>
        <span class="token keyword">new</span> <span class="token class-name">LinkedBlockingQueue</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Runnable</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_5-4-cachedthreadpool"><a href="#_5-4-cachedthreadpool" class="header-anchor">#</a> 5.4 CachedThreadPool</h3> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">ExecutorService</span> <span class="token function">newCachedThreadPool</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token class-name">Integer</span><span class="token punctuation">.</span><span class="token constant">MAX_VALUE</span><span class="token punctuation">,</span>
          <span class="token number">60L</span><span class="token punctuation">,</span> <span class="token class-name">TimeUnit</span><span class="token punctuation">.</span><span class="token constant">SECONDS</span><span class="token punctuation">,</span>
          <span class="token keyword">new</span> <span class="token class-name">SynchronousQueue</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Runnable</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><ul><li>CachedThreadPool的corePool为0，maximumPoolSize为Integer.MAX_VALUE，线程池中的所有线程都不是核心线程。</li> <li>keepAliveTime为60L，unit设置为TimeUnit.SECONDS，空闲线程超过60秒后将会被终止。</li> <li>阻塞队列采用的SynchronousQueue</li></ul> <blockquote><ul><li>SynchronousQueue 不存储元素，数据必须从某个写线程交给某个读线程，而不是写到某个队列中等待被消费。</li> <li>SynchronousQueue 执行put/take操作时，如果队列是空的，或者队列中的节点和当前的线程操作类型一致（如当前操作是 put 操作，而队列中的元素也都是写线程），则将当前线程加入到等待队列。如果队列中有等待节点，而且与当前操作可以匹配（如队列中都是读操作线程，当前线程是写操作线程，反之亦然），则匹配等待队列的队头，出队，返回相应数据。</li></ul></blockquote> <p>理解CachedThreadPool提交任务的过程：</p> <ol><li>第一次提交任务，因为SynchronousQueue需要有读操作与写操作匹配才能写入数据，所以任务不能进入SynchronousQueue队列，而是直接创建一个线程执行任务；</li> <li>之后提交任务，如果线程池里因为空闲线程超时被销毁而没有线程，同样不能进入SynchronousQueue队列，需要创建一个线程执行任务；</li> <li>之后提交任务，如果线程池里的线程都正在执行任务，同样不能进入SynchronousQueue队列，需要创建一个线程执行任务；</li> <li>之后提交任务，如果线程池有线程处于空闲状态（处于空闲状态的线程都会在SynchronousQueue的take()方法上阻塞），那么SynchronousQueue通过offer()方法将任务交给take()执行，不需要创建线程；</li></ol> <blockquote><p>CachedThreadPool的问题：如果主线程提交任务的速度远远大于CachedThreadPool的处理速度，则CachedThreadPool会不断地创建新线程来执行任务，这样有可能会导致系统耗尽CPU和内存资源，所以在使用该线程池时，一定要注意控制并发的任务数，否则创建大量的线程可能导致严重的性能问题。</p></blockquote> <h2 id="_6-执行过程"><a href="#_6-执行过程" class="header-anchor">#</a> 6. 执行过程</h2> <p>这一节详细分析任务提交到线程池之后，线程池是如何处理和执行任务的。</p> <h3 id="_6-1-execute-方法"><a href="#_6-1-execute-方法" class="header-anchor">#</a> 6.1 execute()方法</h3> <p>execute()方法执行过程如下：</p> <ol><li>如果workerCount &lt; corePoolSize，则创建并启动一个线程来执行新提交的任务，<strong>即使有空闲线程，也要创建一个新线程</strong> ；</li> <li>如果workerCount &gt;= corePoolSize，且线程池内的阻塞队列未满，则将任务添加到该阻塞队列中；</li> <li>如果workerCount &gt;= corePoolSize，且线程池内的阻塞队列已满，则创建并启动一个线程来执行新提交的任务；</li> <li>如果workerCount &gt;= maximumPoolSize，且线程池内的阻塞队列已满, 则根据拒绝策略来处理该任务, 默认的处理方式是直接抛异常。</li></ol> <p><img src="/assets/img/20210713006.6d1664b1.png" alt=""></p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">execute</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> command<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>command <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
        <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">NullPointerException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">int</span> c <span class="token operator">=</span> ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">/*
     * 当前核心线程数小于corePoolSize，则新建一个线程放入线程池中。
     * 注意这里不管核心线程有没有空闲，都会创建线程
     */</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">workerCountOf</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> <span class="token operator">&lt;</span> corePoolSize<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// 创建线程，并执行command。addWorker方法后面详细讲解。</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">addWorker</span><span class="token punctuation">(</span>command<span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token keyword">return</span><span class="token punctuation">;</span>
        c <span class="token operator">=</span> ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 如果添加失败，则重新获取ctl值</span>
    <span class="token punctuation">}</span>
    <span class="token comment">// 当前核心线程数大于等于corePoolSize，将任务添加到队列</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isRunning</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> workQueue<span class="token punctuation">.</span><span class="token function">offer</span><span class="token punctuation">(</span>command<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">/*
         * 再次检查线程池的运行状态
         * 如果不是运行状态，将command从workQueue中移除，使用拒绝策略处理command
         */</span>
        <span class="token keyword">int</span> recheck <span class="token operator">=</span> ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">isRunning</span><span class="token punctuation">(</span>recheck<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token function">remove</span><span class="token punctuation">(</span>command<span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token function">reject</span><span class="token punctuation">(</span>command<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 如果有效线程数为0，创建一个线程</span>
        <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">workerCountOf</span><span class="token punctuation">(</span>recheck<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span>
            <span class="token function">addWorker</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment">/*
     * 当前核心线程数大于等于corePoolSize，且workQueue队列添加任务失败，尝试创建maximumPoolSize中的线程来执行任务
     */</span>
    <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">addWorker</span><span class="token punctuation">(</span>command<span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token function">reject</span><span class="token punctuation">(</span>command<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_6-2-addworker方法"><a href="#_6-2-addworker方法" class="header-anchor">#</a> 6.2 addWorker方法</h3> <p>addWorkerr(Runnable firstTask, boolean core)方法的主要工作是在线程池中创建一个新的线程并执行：</p> <ol><li>增加线程数量ctl；</li> <li>创建Worker对象来执行任务，每一个Worker对象都会创建一个线程；</li> <li>worker添加成功后，启动这个worker中的线程</li></ol> <ul><li>参数firstTask：这个新创建的线程需要第一个执行的任务；firstTask==null，表示创建线程，到workQueue中取任务执行；</li> <li>参数core：true代表使用corePoolSize作为创建线程的界限；false代表使用maximumPoolSize作为界限</li></ul> <div class="language-java extra-class"><pre class="language-java"><code><span class="token comment">/**
 * 在线程池中创建一个新的线程并执行
 * @param firstTask 这个新创建的线程需要第一个执行的任务；firstTask==null，表示创建线程，到workQueue中取任务执行
 * @param core true代表使用corePoolSize作为创建线程的界限；false代表使用maximumPoolSize作为界限
 * @return
 */</span>
<span class="token keyword">private</span> <span class="token keyword">boolean</span> <span class="token function">addWorker</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> firstTask<span class="token punctuation">,</span> <span class="token keyword">boolean</span> core<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 1. 增加线程数量ctl</span>
    retry<span class="token operator">:</span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token punctuation">;</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">int</span> c <span class="token operator">=</span> ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">int</span> rs <span class="token operator">=</span> <span class="token function">runStateOf</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 获取运行状态</span>
        <span class="token comment">/*
         * 不能创建线程的几种情况：
         * 1. 线程池已关闭且rs == SHUTDOWN，不允许提交任务，且中断正在执行的任务
         * 2. 线程池已关闭且firstTask!=null，
         * 3. 线程池已关闭且workQueue为空
         */</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>rs <span class="token operator">&gt;=</span> <span class="token constant">SHUTDOWN</span> <span class="token operator">&amp;&amp;</span>
            <span class="token operator">!</span> <span class="token punctuation">(</span>rs <span class="token operator">==</span> <span class="token constant">SHUTDOWN</span> <span class="token operator">&amp;&amp;</span>
               firstTask <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span>
               <span class="token operator">!</span> workQueue<span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
        <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token punctuation">;</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">int</span> wc <span class="token operator">=</span> <span class="token function">workerCountOf</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 获取线程数</span>
            <span class="token comment">// 判断线程数上限</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>wc <span class="token operator">&gt;=</span> <span class="token constant">CAPACITY</span> <span class="token operator">||</span>
                wc <span class="token operator">&gt;=</span> <span class="token punctuation">(</span>core <span class="token operator">?</span> corePoolSize <span class="token operator">:</span> maximumPoolSize<span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
            <span class="token comment">// 尝试增加workerCount，如果成功，则跳出外层for循环</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">compareAndIncrementWorkerCount</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token keyword">break</span> retry<span class="token punctuation">;</span>
            <span class="token comment">// CAS失败，循环尝试</span>
            c <span class="token operator">=</span> ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">runStateOf</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> <span class="token operator">!=</span> rs<span class="token punctuation">)</span>
                <span class="token keyword">continue</span> retry<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">boolean</span> workerStarted <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
    <span class="token keyword">boolean</span> workerAdded <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
    <span class="token class-name">Worker</span> w <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
    <span class="token keyword">try</span> <span class="token punctuation">{</span>
        <span class="token comment">/*
         * 2. 创建Worker对象来执行任务，每一个Worker对象都会创建一个线程
         * Worker类下文详细讲解
         */</span>
        w <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Worker</span><span class="token punctuation">(</span>firstTask<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">final</span> <span class="token class-name">Thread</span> t <span class="token operator">=</span> w<span class="token punctuation">.</span>thread<span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>t <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">final</span> <span class="token class-name">ReentrantLock</span> mainLock <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mainLock<span class="token punctuation">;</span>
            mainLock<span class="token punctuation">.</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">try</span> <span class="token punctuation">{</span>
                <span class="token keyword">int</span> rs <span class="token operator">=</span> <span class="token function">runStateOf</span><span class="token punctuation">(</span>ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token comment">/*
                 * 判断状态：
                 * 小于 SHUTTDOWN 那就是 RUNNING，最正常的情况
                 * 等于 SHUTDOWN，不接受新的任务但是会继续执行等待队列中的任务，所以要求firstTask == null
                 */</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span>rs <span class="token operator">&lt;</span> <span class="token constant">SHUTDOWN</span> <span class="token operator">||</span>
                    <span class="token punctuation">(</span>rs <span class="token operator">==</span> <span class="token constant">SHUTDOWN</span> <span class="token operator">&amp;&amp;</span> firstTask <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                    <span class="token keyword">if</span> <span class="token punctuation">(</span>t<span class="token punctuation">.</span><span class="token function">isAlive</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// precheck that t is startable</span>
                        <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalThreadStateException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    workers<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>w<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 添加worker</span>
                    <span class="token keyword">int</span> s <span class="token operator">=</span> workers<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token comment">// largestPoolSize记录着线程池中出现过的最大线程数量</span>
                    <span class="token keyword">if</span> <span class="token punctuation">(</span>s <span class="token operator">&gt;</span> largestPoolSize<span class="token punctuation">)</span>
                        largestPoolSize <span class="token operator">=</span> s<span class="token punctuation">;</span>
                    workerAdded <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
                mainLock<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
            
            <span class="token comment">// 3. worker添加成功，启动这个worker中的线程</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>workerAdded<span class="token punctuation">)</span> <span class="token punctuation">{</span>
                t<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                workerStarted <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span> workerStarted<span class="token punctuation">)</span>
            <span class="token function">addWorkerFailed</span><span class="token punctuation">(</span>w<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> workerStarted<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_6-3-worker类"><a href="#_6-3-worker类" class="header-anchor">#</a> 6.3 Worker类</h3> <p>线程池中的每一个线程被封装成一个Worker对象，线程池维护的其实就是一组Worker对象。</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">class</span> <span class="token class-name">Worker</span> <span class="token keyword">extends</span> <span class="token class-name">AbstractQueuedSynchronizer</span> <span class="token keyword">implements</span> <span class="token class-name">Runnable</span> <span class="token punctuation">{</span>
    <span class="token comment">// 线程被封装成Worker</span>
    <span class="token keyword">final</span> <span class="token class-name">Thread</span> thread<span class="token punctuation">;</span>
    <span class="token comment">/*
     * 在创建线程的时候，如果同时指定的需要执行的第一个任务。
     * 可以为 null，线程自己到任务队列中取任务执行
     */</span>
    <span class="token class-name">Runnable</span> firstTask<span class="token punctuation">;</span>
    <span class="token comment">// 线程完成的任务数</span>
    <span class="token keyword">volatile</span> <span class="token keyword">long</span> completedTasks<span class="token punctuation">;</span>

    <span class="token comment">// Worker 只有这一个构造方法</span>
    <span class="token class-name">Worker</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> firstTask<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">setState</span><span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// inhibit interrupts until runWorker</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>firstTask <span class="token operator">=</span> firstTask<span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>thread <span class="token operator">=</span> <span class="token function">getThreadFactory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">newThread</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 调用 ThreadFactory 来创建一个新的线程</span>
    <span class="token punctuation">}</span>

    <span class="token comment">/**
     * worker工作，调用外部类的 runWorker 方法，循环等待队列中获取任务并执行，下文详细介绍
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">runWorker</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// ... 其他几个方法用AQS及锁的操作，不关注</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_6-4-runworker方法"><a href="#_6-4-runworker方法" class="header-anchor">#</a> 6.4 runWorker方法</h3> <p>循环从等待队列中获取任务并执行：</p> <ol><li>获取到新任务就执行；</li> <li>获取不到就阻塞等待新任务；</li> <li>队列中没有任务或空闲线程超时，销毁线程。</li></ol> <div class="language-java extra-class"><pre class="language-java"><code><span class="token comment">/**
 * 循环从等待队列中获取任务并执行
 */</span>
<span class="token keyword">final</span> <span class="token keyword">void</span> <span class="token function">runWorker</span><span class="token punctuation">(</span><span class="token class-name">Worker</span> w<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token class-name">Thread</span> wt <span class="token operator">=</span> <span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">currentThread</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token class-name">Runnable</span> task <span class="token operator">=</span> w<span class="token punctuation">.</span>firstTask<span class="token punctuation">;</span>
 w<span class="token punctuation">.</span>firstTask <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
 w<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// allow interrupts</span>
 <span class="token keyword">boolean</span> completedAbruptly <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
 <span class="token keyword">try</span> <span class="token punctuation">{</span>
  <span class="token comment">/*
   * 循环调用 getTask() 获取任务，getTask()下文详细讲解
   * 获取到任务就执行，
   * 获取不到就阻塞等待新任务，
   * 返回null任务就销毁当前线程
   */</span>
  <span class="token keyword">while</span> <span class="token punctuation">(</span>task <span class="token operator">!=</span> <span class="token keyword">null</span> <span class="token operator">||</span> <span class="token punctuation">(</span>task <span class="token operator">=</span> <span class="token function">getTask</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   w<span class="token punctuation">.</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token comment">// 如果线程池状态大于等于 STOP，中断</span>
   <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token function">runStateAtLeast</span><span class="token punctuation">(</span>ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token constant">STOP</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token punctuation">(</span><span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">interrupted</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token function">runStateAtLeast</span><span class="token punctuation">(</span>
     ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token constant">STOP</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>wt<span class="token punctuation">.</span><span class="token function">isInterrupted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    wt<span class="token punctuation">.</span><span class="token function">interrupt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token keyword">try</span> <span class="token punctuation">{</span>
    <span class="token function">beforeExecute</span><span class="token punctuation">(</span>wt<span class="token punctuation">,</span> task<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 钩子方法，留给需要的子类实现</span>
    <span class="token class-name">Throwable</span> thrown <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
    <span class="token keyword">try</span> <span class="token punctuation">{</span>
     task<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 真正执行任务，执行execute()中传入任务的run方法</span>
    <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">RuntimeException</span> x<span class="token punctuation">)</span> <span class="token punctuation">{</span>
     thrown <span class="token operator">=</span> x<span class="token punctuation">;</span>
     <span class="token keyword">throw</span> x<span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Error</span> x<span class="token punctuation">)</span> <span class="token punctuation">{</span>
     thrown <span class="token operator">=</span> x<span class="token punctuation">;</span>
     <span class="token keyword">throw</span> x<span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Throwable</span> x<span class="token punctuation">)</span> <span class="token punctuation">{</span>
     thrown <span class="token operator">=</span> x<span class="token punctuation">;</span>
     <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
     <span class="token function">afterExecute</span><span class="token punctuation">(</span>task<span class="token punctuation">,</span> thrown<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 钩子方法，留给需要的子类实现</span>
    <span class="token punctuation">}</span>
   <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
    task <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
    w<span class="token punctuation">.</span>completedTasks<span class="token operator">++</span><span class="token punctuation">;</span>
    w<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
  completedAbruptly <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
  <span class="token comment">// 如果到这里，需要销毁线程：</span>
  <span class="token comment">// 1. getTask 返回 null退出while循环，队列中没有任务或空闲线程超时</span>
  <span class="token comment">// 2. 任务执行过程中发生了异常</span>
  <span class="token function">processWorkerExit</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> completedAbruptly<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_6-5-gettask方法"><a href="#_6-5-gettask方法" class="header-anchor">#</a> 6.5 getTask方法</h3> <p>获取workQueue中的任务</p> <ol><li>正常情况，直接workQueue.take()获取到任务返回；</li> <li>workQueue中没有任务，当前线程阻塞直到获取到任务；</li> <li>getTask()返回 null， runWorker()方法会销毁当前线程，如下情况返回null：</li></ol> <ul><li>状态为SHUTDOWN &amp;&amp; workQueue.isEmpty()，任务队列没有任务，且即将关闭线程池，销毁当前线程</li> <li>状态 &gt;= STOP，关闭线程池，销毁当前线程</li> <li>当前线程数超过最大maximumPoolSize，销毁当前线程</li> <li>空闲线程超时keepAliveTime，需要销毁线程</li></ul> <div class="language-java extra-class"><pre class="language-java"><code><span class="token comment">/**
 * 获取workQueue中的任务
 * 1. 正常情况，直接workQueue.take()获取到任务返回；
 * 2. workQueue中没有任务，当前线程阻塞直达获取到任务；
 * 3. getTask()返回 null， runWorker()方法会销毁当前线程，如下情况返回null：
 *      状态为SHUTDOWN &amp;&amp; workQueue.isEmpty()
 *      状态 &gt;= STOP
 *      当前线程数 wc &gt; maximumPoolSize
 *      空闲线程超时keepAliveTime
 */</span>
<span class="token keyword">private</span> <span class="token class-name">Runnable</span> <span class="token function">getTask</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">boolean</span> timedOut <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token comment">// Did the last poll() time out?</span>

 <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token punctuation">;</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">int</span> c <span class="token operator">=</span> ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">int</span> rs <span class="token operator">=</span> <span class="token function">runStateOf</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">/*
   * 两种返回null的情况：
   * 1. rs == SHUTDOWN &amp;&amp; workQueue.isEmpty()
   * 2. rs &gt;= STOP
   */</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>rs <span class="token operator">&gt;=</span> <span class="token constant">SHUTDOWN</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>rs <span class="token operator">&gt;=</span> <span class="token constant">STOP</span> <span class="token operator">||</span> workQueue<span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token function">decrementWorkerCount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// CAS 操作，减少工作线程数</span>
   <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">int</span> wc <span class="token operator">=</span> <span class="token function">workerCountOf</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">boolean</span> timed <span class="token operator">=</span> allowCoreThreadTimeOut <span class="token operator">||</span> wc <span class="token operator">&gt;</span> corePoolSize<span class="token punctuation">;</span>

  <span class="token comment">/*
   * 两种返回null的情况：
   * 1. 当前线程数 wc &gt; maximumPoolSize，return null
   * 2. 空闲线程超时，return null
   */</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>wc <span class="token operator">&gt;</span> maximumPoolSize <span class="token operator">||</span> <span class="token punctuation">(</span>timed <span class="token operator">&amp;&amp;</span> timedOut<span class="token punctuation">)</span><span class="token punctuation">)</span>
   <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>wc <span class="token operator">&gt;</span> <span class="token number">1</span> <span class="token operator">||</span> workQueue<span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">compareAndDecrementWorkerCount</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
   <span class="token keyword">continue</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token comment">/*
   * 到 workQueue 中获取任务并返回
   */</span>
  <span class="token keyword">try</span> <span class="token punctuation">{</span>
   <span class="token class-name">Runnable</span> r <span class="token operator">=</span> timed <span class="token operator">?</span>
    workQueue<span class="token punctuation">.</span><span class="token function">poll</span><span class="token punctuation">(</span>keepAliveTime<span class="token punctuation">,</span> <span class="token class-name">TimeUnit</span><span class="token punctuation">.</span><span class="token constant">NANOSECONDS</span><span class="token punctuation">)</span> <span class="token operator">:</span>
    workQueue<span class="token punctuation">.</span><span class="token function">take</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token keyword">if</span> <span class="token punctuation">(</span>r <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> r<span class="token punctuation">;</span>
   timedOut <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> retry<span class="token punctuation">)</span> <span class="token punctuation">{</span>
   timedOut <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_6-6-总结"><a href="#_6-6-总结" class="header-anchor">#</a> 6.6 总结</h3> <ol><li>如果workerCount &lt; corePoolSize，则创建并启动一个线程来执行新提交的任务；</li> <li>如果workerCount &gt;= corePoolSize，且线程池内的阻塞队列未满，则将任务添加到该阻塞队列中；</li> <li>如果workerCount &gt;= corePoolSize，且线程池内的阻塞队列已满，则创建并启动一个线程来执行新提交的任务；</li> <li>如果workerCount &gt;= maximumPoolSize，且线程池内的阻塞队列已满, 则根据拒绝策略来处理该任务, 默认的处理方式是直接抛异常。</li> <li>线程池中的线程执行完当前任务后，会循环到任务队列中取任务继续执行；线程获取队列中任务时会阻塞，直到获取到任务返回；</li></ol> <p><img src="/assets/img/20210713007.6d1664b1.png" alt=""></p> <h2 id="_7-关闭线程池"><a href="#_7-关闭线程池" class="header-anchor">#</a> 7. 关闭线程池</h2> <p>关闭线程池使用shutdown方法或shutdownNow方法，最终目的是将线程池状态设置成TERMINATED。</p> <h3 id="_7-1-shutdown方法"><a href="#_7-1-shutdown方法" class="header-anchor">#</a> 7.1 shutdown方法</h3> <p>shutdown方法过程：</p> <ol><li>将线程池切换到SHUTDOWN状态；</li> <li>调用interruptIdleWorkers方法请求中断所有空闲的worker；</li> <li>调用tryTerminate尝试结束线程池。</li></ol> <div class="language-java extra-class"><pre class="language-java"><code>    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">shutdown</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">final</span> <span class="token class-name">ReentrantLock</span> mainLock <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mainLock<span class="token punctuation">;</span>
        mainLock<span class="token punctuation">.</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">try</span> <span class="token punctuation">{</span>
            <span class="token function">checkShutdownAccess</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 安全策略判断</span>
            <span class="token function">advanceRunState</span><span class="token punctuation">(</span><span class="token constant">SHUTDOWN</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// CAS设置线程池状态为SHUTDOWN</span>
            <span class="token function">interruptIdleWorkers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 中断空闲线程</span>
            <span class="token function">onShutdown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 钩子方法，用于ScheduledThreadPoolExecutor</span>
        <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
            mainLock<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token comment">// 尝试结束线程池，下文详细讲解</span>
        <span class="token function">tryTerminate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</code></pre></div><h3 id="_7-2-tryterminate方法"><a href="#_7-2-tryterminate方法" class="header-anchor">#</a> 7.2 tryTerminate方法</h3> <p>结束线程池，最终将线程池状态设置为TERMINATED。</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token comment">/**
 * 结束线程池，最终将线程池状态设置为TERMINATED
 */</span>
<span class="token keyword">final</span> <span class="token keyword">void</span> <span class="token function">tryTerminate</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token punctuation">;</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">int</span> c <span class="token operator">=</span> ctl<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">/*
   * 当前线程池的状态为以下几种情况时，直接返回：
   * 1. RUNNING，因为还在运行中，不能停止；
   * 2. TIDYING或TERMINATED，已经关闭了；
   * 3. SHUTDOWN并且等待队列非空，这时要执行完workQueue中的task；
   */</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isRunning</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> <span class="token operator">||</span>
   <span class="token function">runStateAtLeast</span><span class="token punctuation">(</span>c<span class="token punctuation">,</span> <span class="token constant">TIDYING</span><span class="token punctuation">)</span> <span class="token operator">||</span>
   <span class="token punctuation">(</span><span class="token function">runStateOf</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token constant">SHUTDOWN</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span> workQueue<span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
   <span class="token keyword">return</span><span class="token punctuation">;</span>
  <span class="token comment">// 如果线程数量不为0，则中断一个空闲的工作线程，并返回</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">workerCountOf</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Eligible to terminate</span>
   <span class="token function">interruptIdleWorkers</span><span class="token punctuation">(</span><span class="token constant">ONLY_ONE</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token keyword">return</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">final</span> <span class="token class-name">ReentrantLock</span> mainLock <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mainLock<span class="token punctuation">;</span>
  mainLock<span class="token punctuation">.</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">try</span> <span class="token punctuation">{</span>
   <span class="token comment">// 尝试设置状态为TIDYING</span>
   <span class="token keyword">if</span> <span class="token punctuation">(</span>ctl<span class="token punctuation">.</span><span class="token function">compareAndSet</span><span class="token punctuation">(</span>c<span class="token punctuation">,</span> <span class="token function">ctlOf</span><span class="token punctuation">(</span><span class="token constant">TIDYING</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">try</span> <span class="token punctuation">{</span>
     <span class="token function">terminated</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 钩子方法，留给子类实现</span>
    <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
     <span class="token comment">// 设置状态为TERMINATED</span>
     ctl<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token function">ctlOf</span><span class="token punctuation">(</span><span class="token constant">TERMINATED</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
     termination<span class="token punctuation">.</span><span class="token function">signalAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span>
  <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
   mainLock<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token comment">// else retry on failed CAS</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_7-3-shutdownnow方法"><a href="#_7-3-shutdownnow方法" class="header-anchor">#</a> 7.3 shutdownNow方法</h3> <p>shutdownNow方法过程：</p> <ol><li>将线程池切换到STOP状态；</li> <li>中断所有工作线程，无论是否空闲；</li> <li>取出阻塞队列中没有被执行的任务并返回；</li> <li>调用tryTerminate尝试结束线程池。</li></ol> <div class="language-java extra-class"><pre class="language-java"><code>    <span class="token keyword">public</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Runnable</span><span class="token punctuation">&gt;</span></span> <span class="token function">shutdownNow</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Runnable</span><span class="token punctuation">&gt;</span></span> tasks<span class="token punctuation">;</span>
        <span class="token keyword">final</span> <span class="token class-name">ReentrantLock</span> mainLock <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mainLock<span class="token punctuation">;</span>
        mainLock<span class="token punctuation">.</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">try</span> <span class="token punctuation">{</span>
            <span class="token function">checkShutdownAccess</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 安全策略判断</span>
            <span class="token function">advanceRunState</span><span class="token punctuation">(</span><span class="token constant">STOP</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// CAS设置线程池状态为STOP</span>
            <span class="token function">interruptWorkers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 中断所有工作线程，无论是否空闲</span>
            tasks <span class="token operator">=</span> <span class="token function">drainQueue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 取出阻塞队列中没有被执行的任务并返回</span>
        <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
            mainLock<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token function">tryTerminate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 结束线程池，最终将线程池状态设置为TERMINATED</span>
        <span class="token keyword">return</span> tasks<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</code></pre></div><blockquote><p>shutdown方法 VS shutdownNow方法</p> <ul><li>shutdown方法设置线程池状态为SHUTDOWN，SHUTDOWN状态不再接受新提交的任务，但却可以继续处理阻塞队列中已保存的任务。</li> <li>shutdownNow方法设置线程池状态为STOP，STOP状态不能接受新任务，也不处理队列中的任务，会中断正在处理任务的线程。</li></ul></blockquote> <h2 id="_8-其他问题"><a href="#_8-其他问题" class="header-anchor">#</a> 8. 其他问题</h2> <p>一些不需要长篇大论介绍的知识点，这里简单说下。</p> <h3 id="_8-1-任务拒绝策略"><a href="#_8-1-任务拒绝策略" class="header-anchor">#</a> 8.1 任务拒绝策略</h3> <p>构造线程时传入的 RejectedExecutionHandler 类型参数 handler 就是拒绝策略。</p> <p>RejectedExecutionHandler只有一个钩子方法，执行拒绝策略。</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">RejectedExecutionHandler</span> <span class="token punctuation">{</span>
    <span class="token keyword">void</span> <span class="token function">rejectedExecution</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> r<span class="token punctuation">,</span> <span class="token class-name">ThreadPoolExecutor</span> executor<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>ThreadPoolExecutor 中有四个已经定义好的RejectedExecutionHandler实现类可供我们直接使用。（我们也可以实现自己的策略）</p> <div class="language-java extra-class"><pre class="language-java"><code>    <span class="token comment">/**
     * 由提交任务的线程自己来执行这个任务
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">CallerRunsPolicy</span> <span class="token keyword">implements</span> <span class="token class-name">RejectedExecutionHandler</span> <span class="token punctuation">{</span>
        <span class="token keyword">public</span> <span class="token class-name">CallerRunsPolicy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">rejectedExecution</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> r<span class="token punctuation">,</span> <span class="token class-name">ThreadPoolExecutor</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>e<span class="token punctuation">.</span><span class="token function">isShutdown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                r<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token comment">/**
     * 默认的策略：接抛出 RejectedExecutionException 异常
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">AbortPolicy</span> <span class="token keyword">implements</span> <span class="token class-name">RejectedExecutionHandler</span> <span class="token punctuation">{</span>
        <span class="token keyword">public</span> <span class="token class-name">AbortPolicy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">rejectedExecution</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> r<span class="token punctuation">,</span> <span class="token class-name">ThreadPoolExecutor</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">RejectedExecutionException</span><span class="token punctuation">(</span><span class="token string">&quot;Task &quot;</span> <span class="token operator">+</span> r<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span>
                                                 <span class="token string">&quot; rejected from &quot;</span> <span class="token operator">+</span>
                                                 e<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token comment">/**
     * 不做任何处理，直接忽略掉这个任务
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">DiscardPolicy</span> <span class="token keyword">implements</span> <span class="token class-name">RejectedExecutionHandler</span> <span class="token punctuation">{</span>
        <span class="token keyword">public</span> <span class="token class-name">DiscardPolicy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">rejectedExecution</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> r<span class="token punctuation">,</span> <span class="token class-name">ThreadPoolExecutor</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token comment">/**
     * 把队列队头的任务(也就是等待了最长时间的)直接扔掉，然后提交这个任务到等待队列中
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">DiscardOldestPolicy</span> <span class="token keyword">implements</span> <span class="token class-name">RejectedExecutionHandler</span> <span class="token punctuation">{</span>
        <span class="token keyword">public</span> <span class="token class-name">DiscardOldestPolicy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">rejectedExecution</span><span class="token punctuation">(</span><span class="token class-name">Runnable</span> r<span class="token punctuation">,</span> <span class="token class-name">ThreadPoolExecutor</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>e<span class="token punctuation">.</span><span class="token function">isShutdown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                e<span class="token punctuation">.</span><span class="token function">getQueue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">poll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                e<span class="token punctuation">.</span><span class="token function">execute</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
</code></pre></div><h3 id="_8-2-线程池的监控"><a href="#_8-2-线程池的监控" class="header-anchor">#</a> 8.2 线程池的监控</h3> <p>我们可以通过线程池提供的参数和方法对线程池进行监控：</p> <ul><li>getTaskCount：线程池已经执行的和未执行的任务总数；</li> <li>getCompletedTaskCount：线程池已完成的任务数量，该值小于等于taskCount；</li> <li>getLargestPoolSize：线程池曾经创建过的最大线程数量。通过这个数据可以知道线程池是否满过，也就是达到了maximumPoolSize；</li> <li>getPoolSize：线程池当前的线程数量；</li> <li>getActiveCount：当前线程池中正在执行任务的线程数量；</li> <li>实现钩子方法beforeExecute方法，afterExecute方法和terminated方法，增加一些新操作。</li></ul> <h3 id="_8-3-线程池中的线程初始化"><a href="#_8-3-线程池中的线程初始化" class="header-anchor">#</a> 8.3 线程池中的线程初始化</h3> <p>默认情况下，创建线程池之后，线程池中是没有线程的，需要提交任务之后才会创建线程。如果需要线程池创建之后立即创建线程，可以通过以下两个方法实现：</p> <ul><li>prestartCoreThread()：初始化一个核心线程；</li> <li>prestartAllCoreThreads()：初始化所有核心线程。</li></ul> <h3 id="_8-4-线程池容量的动态调整"><a href="#_8-4-线程池容量的动态调整" class="header-anchor">#</a> 8.4 线程池容量的动态调整</h3> <p>ThreadPoolExecutor提供了动态调整线程池容量大小的方法：</p> <ul><li>setCorePoolSize：设置核心池大小</li> <li>setMaximumPoolSize：设置线程池最大能创建的线程数目大小</li></ul> <div class="custom-block tip"><p class="custom-block-title">来源</p> <p><a href="https://mp.weixin.qq.com/s?__biz=MzAxMjEwMzQ5MA==&amp;mid=2448892737&amp;idx=2&amp;sn=e7130bd806fe95feba13cb5cee91741f&amp;scene=21#wechat_redirect" target="_blank" rel="noopener noreferrer">java进阶架构师-深入理解线程池(上)
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://mp.weixin.qq.com/s?__biz=MzAxMjEwMzQ5MA==&amp;mid=2448892892&amp;idx=2&amp;sn=e40719d22817b8fdcabb14cc86c627cb&amp;scene=21#wechat_redirect" target="_blank" rel="noopener noreferrer">java进阶架构师-深入理解线程池(下)
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p></div></div></div> <!----> <div class="page-edit"><!----> <div class="tags"><a href="/tags/?tag=%E5%B9%B6%E5%8F%91%E5%A4%9A%E7%BA%BF%E7%A8%8B" title="标签">#并发多线程</a></div> <!----></div> <div class="page-nav-wapper"><div class="page-nav-centre-wrap"><a href="/pages/f0d781/" class="page-nav-centre page-nav-centre-prev"><div class="tooltip">并发编程三大核心问题</div></a> <a href="/pages/6c4806/" class="page-nav-centre page-nav-centre-next"><div class="tooltip">线程池</div></a></div> <div class="page-nav"><p class="inner"><span class="prev">
        ←
        <a href="/pages/f0d781/" class="prev">并发编程三大核心问题</a></span> <span class="next"><a href="/pages/6c4806/">线程池</a>→
      </span></p></div></div></div> <!----></main></div> <div class="footer"><div class="icons"><a href="mailto:likanjia@126.com" title="发邮件" target="_blank" class="iconfont icon-youjian"></a><a href="https://github.com/" title="GitHub" target="_blank" class="iconfont icon-github"></a><a href="https://music.163.com/#/playlist?id=755597173" title="听音乐" target="_blank" class="iconfont icon-erji"></a></div> 
  Theme by
  <a href="https://github.com/xugaoyi/vuepress-theme-vdoing" target="_blank" title="本站主题">Vdoing</a> 
    | Copyright © 2019-2023
    <span>likanjie | MIT License</span></div> <div class="buttons"><div title="返回顶部" class="button blur go-to-top iconfont icon-fanhuidingbu" style="display:none;"></div> <div title="去评论" class="button blur go-to-comment iconfont icon-pinglun" style="display:none;"></div> <div title="主题模式" class="button blur theme-mode-but iconfont icon-zhuti"><ul class="select-box" style="display:none;"><li class="iconfont icon-zidong">
          跟随系统
        </li><li class="iconfont icon-rijianmoshi">
          浅色模式
        </li><li class="iconfont icon-yejianmoshi">
          深色模式
        </li><li class="iconfont icon-yuedu">
          阅读模式
        </li></ul></div></div> <!----> <!----> <!----></div><div class="global-ui"></div></div>
    <script src="/assets/js/app.c5f14b06.js" defer></script><script src="/assets/js/2.0bb8723e.js" defer></script><script src="/assets/js/7.00cec9d7.js" defer></script>
  </body>
</html>
